package il.technion.cs236369.webserver;

import java.io.StringReader;
import java.util.LinkedList;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

/**
 * @author Eran Arbel
 * 
 * An XML to JSON converter.
 * Initialize by instantiating with the source XML in String form
 * Call convert to get the JSON version
 *
 */
public class XML2JSON
{
	String source;
	Document doc;
	
	public XML2JSON (String xml)
	{
		this.source = xml;
	}
	
	public String convert()
	{
		StringBuilder result = new StringBuilder();			// The returned result
		InputSource is = new InputSource();					// converting the incoming xml
		is.setCharacterStream(new StringReader(source));	// into a readable stream
		
		// initialize XML reader
		SAXReader reader = new SAXReader();
		// try to read the xml into a document
		try
		{
			doc = reader.read(is);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		
		// begin parsing tags
		LinkedList<Element> elemList = new LinkedList<Element>();
		elemList.addFirst(doc.getRootElement());
		
		result.append("{");									// start json 

		buildStringFromElements(elemList, result);
		
		result.append("}");
		
		return result.toString();
	}

	@SuppressWarnings("unchecked")
	private StringBuilder buildStringFromElements(LinkedList<Element> elemList, StringBuilder result)
	{
		while (!elemList.isEmpty())
		{
			Element elem = elemList.removeFirst();					// grab the first tag
			
			boolean tagIsEmpty = true;

			result.append("\"" + elem.getName() + "\": {");			// print it

			for (int i = 0; i < elem.attributeCount(); i++)			// then start counting attributes
			{
				result.append("\"-" + elem.attribute(i).getName()	// add attribute name
						+ "\": \"" + elem.attribute(i).getText()	// and attribute text
						+ "\"");

				result.append(", ");								// maybe there are more attributes or text
				tagIsEmpty = false;
			}

			String text = elem.getText();							// check for text
			text = text.trim();										// clean whitespace only texts
			if (!text.isEmpty())									// if text exists
			{
				result.append("\"#text\": \"" +						// then print the text
						text + "\"");								
				result.append(", ");								// maybe there are child tags
				tagIsEmpty = false;
			}

			if (!elem.elements().isEmpty())							// check if there are child tags
			{
				buildStringFromElements(new LinkedList<Element>(elem.elements()), result);	// if so, go deeper
				result.append("} ");								// and close off the list of children
				tagIsEmpty = false;
			}
			
			if (!tagIsEmpty)
				result.delete(result.length()-2,result.length());		// and make sure we don't have a trailing ", "
			if (elemList.isEmpty())
			{
				result.append("} ");								// but close off the tag anyway
			} else
			{
				result.append("}, ");
			}
		}

		return result;
	}

}